package control;
import model.Sudoku;

/*
 * Diese Klasse dient zum Loesen der Sudokus.
 */

public class SudokuLoeser {
	
	boolean loesbar=true;
	
	int spaltenMerker=0;
	
	int zeilenMerker=0;
	
	private Sudoku sudoku;
	
	private Sudoku sudokuKopie;
	
	boolean nichtLoesbar=false;

	public SudokuLoeser(Sudoku sudoku) {
		this.sudoku = sudoku;
		sudokuKopie = new Sudoku();
		for (int i=0; i<9; i++) {
			for (int j=0; j<9; j++) {
				sudokuKopie.byteSudokuFeld[i][j]=sudoku.byteSudokuFeld[i][j];
			}
		}
	}
	
	public Sudoku getSudoku() {
		return sudoku;
	}
	
	public void setSudoku(Sudoku sudoku){
		this.sudoku = sudoku;
	}
	
	// Loest das Sudoku mit Hilfe von Backtracking
	public void loeseMitBacktracking() {
			// Zum naechsten Feld gehen, welches 0 ist			
			for (byte byteZeile = 0; byteZeile < 9; byteZeile++) {
				for (byte byteSpalte = 0; byteSpalte < 9; byteSpalte++) {
					if (sudoku.byteSudokuFeld[byteZeile][byteSpalte] == 0) {
						do {
							// Erhöhe solange das Feld, bis es richtig ist
							do {
								sudoku.byteSudokuFeld[byteZeile][byteSpalte]++;
							} while (sudoku.pruefeRichtigkeit() != true);
							// Wenn der Wert des Feldes 10 erreicht, setze ihn auf 0 zurück und brich die Funktion ab
							if (sudoku.byteSudokuFeld[byteZeile][byteSpalte] == 10) {
								sudoku.byteSudokuFeld[byteZeile][byteSpalte] = 0;
								return;
							}
							loeseMitBacktracking();
						} while (sudoku.pruefeObVollstaendig() != true);
					}
				}
			}
	}
	
	private void pruefeMitBacktracking(long endTimeMillis) {
		// Zum naechsten Feld gehen, welches 0 ist
		for (byte byteZeile = 0; byteZeile < 9; byteZeile++) {
			for (byte byteSpalte = 0; byteSpalte < 9; byteSpalte++) {
				if (sudokuKopie.byteSudokuFeld[byteZeile][byteSpalte] == 0) {
					do {
						// Erhöhe solange das Feld, bis es richtig ist
						do {
							sudokuKopie.byteSudokuFeld[byteZeile][byteSpalte]++;
						} while (sudokuKopie.pruefeRichtigkeit() != true);
						// Wenn der Wert des Feldes 10 erreicht, setze ihn auf 0 zurück und brich die Funktion ab
						if (sudokuKopie.byteSudokuFeld[byteZeile][byteSpalte] == 10) {
							sudokuKopie.byteSudokuFeld[byteZeile][byteSpalte] = 0;
							return;
						}
						if (endTimeMillis > System.currentTimeMillis()) {
							pruefeMitBacktracking(endTimeMillis);
						}
						else {
							loesbar=false;
							nichtLoesbar=true;
							return;
						}
					} while (sudokuKopie.pruefeObVollstaendig() != true);
				}
			}
		}
		return;
	}
	
	public boolean nichtLoesbarMitBacktracking() {
		nichtLoesbar=false;
		loesbar=true;
		
		// Prüft das Sudoku mit Hilfe von Backtracking
		Thread thread = new Thread(new Runnable() {
			
			
			@Override
			public void run() {
				while (loesbar) {
					long endTimeMillis = System.currentTimeMillis()+200;
					pruefeMitBacktracking(endTimeMillis);
					return;
				}
			}
		});
		thread.start();
		long endTimeMillis = System.currentTimeMillis()+200;
		while (thread.isAlive()) {
			if (System.currentTimeMillis() > endTimeMillis) {
				loesbar=false;
				nichtLoesbar=true;
				break;
			}
		}
		return nichtLoesbar;
	}
	
	
}
